package com.leaf.lowcode.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.leaf.lowcode.API.AppointmentApi;
import com.leaf.lowcode.entity.VisitBean;
import com.leaf.lowcode.entity.VisitorAppointInfo;
import com.leaf.lowcode.entity.VisitorInfo;
import com.leaf.lowcode.entity.VisitorRequest;
import com.leaf.lowcode.mapper.VisitorAppointMapper;
import com.leaf.lowcode.mapper.VisitorMapper;
import com.leaf.lowcode.utils.RegularInstance;
import com.leaf.lowcode.utils.RsaUtil;
import com.leaf.lowcode.utils.StringUtil;
import com.leaf.lowcode.utils.jsontobean.JsonToBeanV;
import com.tencent.welink.iot.SubDeviceDTO;
import com.tencent.welink.iot.WelinkHttp;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 道一云电投一一样的
 */
@Component
public class DaoYiYunApiEventSend {
    /**
     * 访客CRUD
     */
    @Autowired
    private VisitorMapper visitorMapper;
    private VisitorAppointMapper visitorAppointMapper;

    private static final Logger logger = LogManager.getLogger(DaoYiYunApiEventSend.class);

    private static final String DAO_YI_YUN_URL = "https://work.spic.com.cn:8443/mgr/visitor/open/getRecord.do?token=";
    private static final String WELINK_REPORT_SN = "dyyfkgdtsn";
    private static final int WELINK_MODULE_ID = 200738;
    private static final String DAY_PATTERN = "yyyy-MM-dd";
    private static final String TIME_PATTERN = "yyyy-MM-dd'T'HH:mm:ssZZ";

    /**
     * 定时获取道一云接口
     */
    @Scheduled(initialDelay = 60 * 1000 * 1, fixedRate = 60 * 2000 * 1)
    public void execute() throws Exception {
        logger.info("Start fetching visitor apply records...");

        String startDayStr = getStartDayStr(1);
        String endDayStr = getTodayStr();
/*        String requestMsg = " {\n" + "            \"visitAppointedTimeStart\":\"" + startDayStr + "\",\n"
                + "                \"visitAppointedTimeEnd\":\"" + endDayStr + "\",\n"
                + "            \"visitorUserName\":\"\"\n" + "        }";
        */
        String requestMsg = " {\n" +
                "            \"visitAppointedTimeStart\":\"2021-01-01\",\n" +
                "                \"visitAppointedTimeEnd\":\"2021-12-01\",\n" +
                "            \"visitorUserName\":\"\"\n" +
                "        }";




        logger.info("RequestMsg: " + requestMsg);



        /**
         * 加密解密
         */
        String publicKey = new RsaUtil("rsapublic.xml").Key();
        EncrypRSA rsa = new EncrypRSA();
        byte[] ciphertextPublic = rsa.encrypt(publicKey, requestMsg, "PUBLIC");
        String encryptedRequest = new String(Base64.getEncoder().encode(ciphertextPublic));

        String records = getVisitApplyRecords(encryptedRequest);
        JSONObject objects = JSON.parseObject(records);
        String code = (String) objects.get("code");
        if (null == code || !code.equals("0")) {
            logger.error("Wrong return code from DaoYi Cloud, code: " + code);
            return;
        }

        if (!objects.containsKey("data")) {
            logger.error("Wrong record data from DaoYi Cloud, objects: " + objects);
            return;
        }

        JSONArray visitorList = (JSONArray) ((JSONObject) objects.get("data")).get("data");

        for (Object o : visitorList) {
            JSONObject visitorJson = (JSONObject) o;
            String applyId = (String) visitorJson.get("id");
            // 查询
            String flag = visitorMapper.selectId(applyId);

            if (flag == null) {
                logger.info("New apply record, store to database and report to WeLink.");
                JsonToBeanV<VisitBean> jsonToBeanV = new JsonToBeanV<>();
                // 自己写的工具类jsonToBeanV，JSON值注入到Javabean中
                VisitBean visitBean = new VisitBean();
                jsonToBeanV.tansfrom(visitBean, visitorJson);
                visitorMapper.insert(visitBean);
                logger.info("Record stored to visitor_info.");

                AppointmentApi appointmentApi = new AppointmentApi();

                // 访客免登记
                VisitorRequest visitorRequest = getVisitorRequest(visitBean);
                String re = appointmentApi.visitorAppointment(visitorRequest);
                logger.info("Appointed to HaiKang: " + re);

                VisitorAppointInfo visitorAppointInfo = getVisitorAppointInfo(re);
                visitorAppointMapper.insert(visitorAppointInfo);
                logger.info("Record stored to visitor_appoint.");

                reportToWeLink(visitorAppointInfo, visitorRequest);
                logger.info("Reported to WeLink.");
            }
        }
    }

    private String getVisitApplyRecords(String encryptedRequest) {
        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders headers = new HttpHeaders();

        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        MultiValueMap<String, String> multiValueMap = new LinkedMultiValueMap<>();
        multiValueMap.add("json", encryptedRequest);

        // 封装
        HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(multiValueMap, headers);
        String token = getToken();
//        String url="https://workuat.spic.com.cn/mgr/visitor/open/getRecord.do?token=";
        String urltoken = DAO_YI_YUN_URL + token;

        ResponseEntity<String> responseEntity = restTemplate.exchange(urltoken, HttpMethod.POST, request, String.class);

        logger.info(responseEntity.getStatusCode());
        logger.info(responseEntity.getStatusCodeValue());
        logger.info(responseEntity.getHeaders());
        String body = responseEntity.getBody();
        logger.info("=================" + body + "===============================");

        logger.info("========================"+responseEntity.getStatusCode()+"====================================");

        logger.info("========================"+responseEntity.getStatusCodeValue()+"====================================");


        return body;
    }

    private VisitorRequest getVisitorRequest(VisitBean visitBean) {
        VisitorRequest visitorRequest = new VisitorRequest();
        visitorRequest.setReceptionistId("f6436575d656415eac49aff1b37024fd");
        visitorRequest.setPersonNum(1);
        VisitorInfo visitorInfo = new VisitorInfo();
        visitorInfo.setGender(1);
        visitorInfo.setVisitorName(visitBean.getVisitorUserName());
        visitorInfo.setPhoneNo(visitBean.getVisitorUserPhone());
        visitorInfo.setCertificateNo(visitBean.getVisitorUserIdNumber());
        visitorInfo.setCertificateType(111);
        visitorInfo.setNation(1);
        visitorRequest.setVisitStartTime(visitBean.getVisitAppointedTime());
        visitorRequest.setVisitEndTime(getEndTimeStr(visitBean.getVisitAppointedTime()));
        visitorRequest.setVisitorInfo(visitorInfo);

        return visitorRequest;
    }

    private VisitorAppointInfo getVisitorAppointInfo(String info) {
        JSONObject jsonInfo = JSON.parseObject(info);
        JSONObject dataInfo = (JSONObject) jsonInfo.get("data");
        logger.info("dataInfo: " + dataInfo);
        VisitorAppointInfo visitorAppointInfo = new VisitorAppointInfo();
        JsonToBeanV<VisitorAppointInfo> jsonToBeanV = new JsonToBeanV<VisitorAppointInfo>();
        // 自己写的工具类jsonToBeanV，JSON值注入到Javabean中
        visitorAppointInfo = jsonToBeanV.tansfrom(visitorAppointInfo, dataInfo);

        visitorAppointInfo.setCode((String) jsonInfo.get("code"));
        visitorAppointInfo.setMsg((String) jsonInfo.get("msg"));

        return visitorAppointInfo;
    }

    private void reportToWeLink(VisitorAppointInfo visitInfo, VisitorRequest visitorRequest) {
        List<SubDeviceDTO> subDeviceDTOList = RegularInstance.subDeviceDTOList;
        if (null == subDeviceDTOList) {
            logger.error("Get device list failure!");
        } else {
            for (SubDeviceDTO dto : subDeviceDTOList) {
                String sn = dto.getSn();
                if (WELINK_REPORT_SN.equals(sn)) {
                    logger.info("Reporting WeLink data for sn: " + sn);
                    JSONObject standardData = new JSONObject();
                    standardData.put("reportTs", System.currentTimeMillis());
                    JSONObject profile = new JSONObject();
                    profile.put("modelId", WELINK_MODULE_ID);
                    profile.put("appType", "visitor");
                    profile.put("pioCode", "w0717006");
                    standardData.put("profile", profile);

                    JSONObject events = new JSONObject();
                    JSONObject event = new JSONObject();
                    event.put("alarmLevel", 1);
                    event.put("eventType", 0);
                    event.put("eventTs", System.currentTimeMillis());
                    event.put("describe", "");
                    event.put("orderId", visitInfo.getOrderId());
                    event.put("visitorUserName", StringUtil.strToUnicode(visitInfo.getVisitorName()));
                    event.put("beVisitUserName", StringUtil.strToUnicode(visitInfo.getReceptionistName()));
                    event.put("visitStartTime", visitorRequest.getVisitStartTime());
                    event.put("visitEndTime", visitorRequest.getVisitEndTime());

                    events.put("appointment", event);

                    standardData.put("events", events);
                    standardData.put("properties", new JSONObject());
                    String devRunEvent = JSONObject.toJSONString(standardData, SerializerFeature.WriteMapNullValue);

                    WelinkHttp wh = new WelinkHttp(RegularInstance.registerData1, RegularInstance.loginData);
                    try {
                        logger.info("Start report to WeLink...");
                        wh.sendMessage(RegularInstance.loginData.load(), 80000, Long.parseLong(dto.getDin()), devRunEvent, true);
                        logger.info("Reported to WeLink.");
                    } catch (MqttException e) {
                        logger.error("report to WeLink failure! " + e.getMessage());
                        e.printStackTrace();
                    }

                    break;
                }
            }
        }
    }

    /**
     * private String getStartTimeStr() {
     * Calendar calendar = new GregorianCalendar();
     * calendar.add(Calendar.DAY_OF_MONTH,0);
     * String pattern = "YYYY-MM-dd'T'HH:mm:ssZZ";
     * //一天的开始时间 yyyy:MM:dd 00:00:00
     * calendar.set(Calendar.HOUR_OF_DAY,0);
     * calendar.set(Calendar.MINUTE,0);
     * calendar.set(Calendar.SECOND,0);
     * calendar.set(Calendar.MILLISECOND,0);
     * Date dayStart = calendar.getTime();
     * <p>
     * return DateFormatUtils.format(dayStart,pattern);
     * }
     */

    private String getTodayStr() {
        SimpleDateFormat dateFormat = new SimpleDateFormat(DAY_PATTERN);
        return dateFormat.format(new Date());
    }

    private String getStartDayStr(int days) {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.WEEK_OF_YEAR, -1 * days);
        SimpleDateFormat dateFormat = new SimpleDateFormat(DAY_PATTERN);
        return dateFormat.format(cal.getTime());
    }

    private String getEndTimeStr(String appointTimeStr) {
        DateFormat formatter = new SimpleDateFormat(DAY_PATTERN);
        try {
            Date startDate = formatter.parse(appointTimeStr);
            Calendar calendar = new GregorianCalendar();
            calendar.setTime(startDate);

            //一天的结束时间 yyyy:MM:dd 00:00:00
            calendar.set(Calendar.HOUR_OF_DAY, 23);
            calendar.set(Calendar.MINUTE, 59);
            calendar.set(Calendar.SECOND, 59);
            calendar.set(Calendar.MILLISECOND, 999);
            Date dayEnd = calendar.getTime();

            return DateFormatUtils.format(dayEnd, TIME_PATTERN);
        } catch (ParseException e) {
            e.printStackTrace();
        }

        return "";
    }

    private String getToken() {
        /**
         * 获取token
         */
        QueryToken queryToken = new QueryToken();
        return queryToken.execute();
    }

    public static void main(String[] args) {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DAY_OF_YEAR, -1);
        SimpleDateFormat dateFormat = new SimpleDateFormat(DAY_PATTERN);
        System.out.println(dateFormat.format(cal.getTime()));
    }
}
